package com.bryantkobe.myspringcode.handler;

import com.bryantkobe.myspringcode.exception.BusinessException;
import com.bryantkobe.myspringcode.exception.ErrorResult;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.NativeWebRequest;

import java.nio.file.AccessDeniedException;
import java.util.stream.Collectors;

/**
 * @description: 全局异常处理类
 * @author: alienwarezzl
 * @date: 2025/9/22
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    // 处理业务异常
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResult> handleBusinessException(BusinessException e,
                                               NativeWebRequest request) {
        logger.warn("业务异常: {} - {}", e.getErrorCode(), e.getMessage());

        HttpServletRequest httpRequest = request.getNativeRequest(HttpServletRequest.class);
        String path = httpRequest != null ? httpRequest.getRequestURI() : "unknown";

        ErrorResult errorResult = ErrorResult.of(
                HttpStatus.BAD_REQUEST.value(),
                e.getErrorCode(),
                e.getMessage(),
                path
        );

        // 添加异常参数到响应中（用于前端调试）
        if (!e.getErrorParams().isEmpty()) {
            errorResult = errorResult.withParams(e.getErrorParams());
        }

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResult);
    }

    /**
     * 处理AssertionError（Java原生assert关键字抛出的异常）
     */
    @ExceptionHandler(AssertionError.class)
    public ResponseEntity<ErrorResult> handleAssertionError(AssertionError e,
                                                            NativeWebRequest request) {
        logger.warn("断言失败: {}", e.getMessage());

        HttpServletRequest httpRequest = request.getNativeRequest(HttpServletRequest.class);
        String path = httpRequest != null ? httpRequest.getRequestURI() : "unknown";

        // 将AssertionError转换为业务异常响应
        ErrorResult errorResult = ErrorResult.of(
                HttpStatus.BAD_REQUEST.value(),
                "ASSERTION_FAILED",
                e.getMessage() != null ? e.getMessage() : "断言条件不满足",
                path
        );

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResult);
    }

    // 使用JDK21模式匹配处理多种异常类型
    @ExceptionHandler(Exception.class)
    public ErrorResult handleGenericException(Exception e, NativeWebRequest nativeWebRequest) {
        logger.error("系统内部出现未知异常: {}", e.getMessage());
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        if (request == null) {
            return ErrorResult.of(500, "INTERNAL_ERROR", "系统内部错误","");
        }
        return switch (e) {
            case AccessDeniedException accessDenied ->
                    ErrorResult.of(403, "ACCESS_DENIED", "权限不足",
                            request.getRequestURI());
            case MethodArgumentNotValidException validationEx -> {
                String errorMsg = extractValidationError(validationEx);
                yield ErrorResult.of(422, "VALIDATION_ERROR", errorMsg,
                        request.getRequestURI());
            }
            default -> {
                logger.error("Unhandled exception occurred", e);
                yield ErrorResult.of(500, "INTERNAL_ERROR", "系统内部错误",
                        request.getRequestURI());
            }
        };
    }

    private String extractValidationError(MethodArgumentNotValidException ex) {
        return ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(error -> error.getField() + ": " + error.getDefaultMessage())
                .collect(Collectors.joining("; "));
    }
}
